﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Data;
using System.Linq;
using System.Text;
using Caliburn.Core.InversionOfControl;
using Caliburn.PresentationFramework;
using Caliburn.PresentationFramework.Filters;
using Caliburn.PresentationFramework.Invocation;
using Caliburn.PresentationFramework.RoutedMessaging;
using Caliburn.ShellFramework.Results;
using MTGenome.Framework;
using MTGenome.MTG;

namespace MTGenome.ViewModels
{
    [Singleton(typeof(FilterViewModel)), PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class FilterViewModel : PropertyChangedBase
    {
        private bool _anyType = true,
            _anyColor = true,
            _anyExpansion = true;
        private ExpansionViewModel[] _expansions = null;
        private string _searchText = null;
        private CardCollectionViewModel _cardCollection = null;

        public FilterViewModel(CardCollectionViewModel cardCollection)
        {
            _cardCollection = cardCollection;
            Blue =
                Black =
                Red =
                Green =
                White =
                Colorless =
                Artifacts =
                Creatures =
                Lands =
                Enchantments =
                Sorceries =
                Instants =
                Plainswalkers = true;
        }


        #region Public Properties
        public bool Blue
        {
            get;
            set;
        }

        public bool Black
        {
            get;
            set;
        }

        public bool Red
        {
            get;
            set;
        }

        public bool Green
        {
            get;
            set;
        }

        public bool White
        {
            get;
            set;
        }

        public ExpansionViewModel[] Expansions
        {
            get { return _expansions; }
        }

        public bool AnyColor
        {
            get { return _anyColor; }
            set
            {
                if (_anyColor != value)
                {
                    _anyColor = value;
                    NotifyOfPropertyChange(() => AnyColor);
                    NotifyOfPropertyChange(() => NotAnyColor);
                }
            }
        }

        public bool NotAnyColor
        {
            get { return !AnyColor; }
        }

        public bool AnyType
        {
            get { return _anyType; }
            set
            {
                if (_anyType != value)
                {
                    _anyType = value;
                    NotifyOfPropertyChange(() => AnyType);
                    NotifyOfPropertyChange(() => NotAnyType);
                }
            }
        }

        public bool NotAnyType
        {
            get { return !AnyType; }
        }

        public bool AnyExpansion
        {
            get { return _anyExpansion; }
            set
            {
                if (_anyExpansion != value)
                {
                    _anyExpansion = value;
                    NotifyOfPropertyChange(() => AnyExpansion);
                    NotifyOfPropertyChange(() => NotAnyExpansion);
                }
            }
        }

        public bool NotAnyExpansion
        {
            get { return !AnyExpansion; }
        }

        public bool Artifacts
        {
            get;
            set;
        }

        public bool Creatures
        {
            get;
            set;
        }

        public bool Lands
        {
            get;
            set;
        }

        public bool Enchantments
        {
            get;
            set;
        }

        public bool Sorceries
        {
            get;
            set;
        }

        public bool Instants
        {
            get;
            set;
        }

        public bool Plainswalkers
        {
            get;
            set;
        }

        public bool Colorless
        {
            get;
            set;
        }

        public Color Color
        {
            get
            {
                Color color = Color.Colorless;
                if (Black)
                {
                    color |= Color.Black;
                }
                if (Blue)
                {
                    color |= Color.Blue;
                }
                if (Red)
                {
                    color |= Color.Red;
                }
                if (Green)
                {
                    color |= Color.Green;
                }
                if (White)
                {
                    color |= Color.White;
                }
                return color;
            }
        }

        #endregion

        public BindableCollection<ICard> Results
        {
            get;
            set;
        }

        public string SearchText
        {
            get { return _searchText; }
            set { _searchText = value; NotifyOfPropertyChange(() => SearchText); }
        }

        public string[] AutoCompleateResults
        {
            get;
            set;
        }


        public IEnumerable<IResult> Loaded()
        {
            yield return new FocusResult(this, "SearchText");

            using (IDatabase database = IoC.Get<IDatabase>())
            {
                _expansions = database.Expansions
                    .OrderBy(e => e.Name)
                    .AsEnumerable()
                    .Select(e => (ExpansionViewModel)IoC.Get<ExpansionViewModel>().WithSubject(e))
                    .ToArray();
                NotifyOfPropertyChange(() => Expansions);
            }
        }

        public IEnumerable<IResult> UpdateAutoCompleateResults()
        {
            yield return new AsyncResult(() =>
            {
                using (IDatabase database = IoC.Get<IDatabase>())
                {
                    var query = database.Cards;

                    //Text filter
                    if (!string.IsNullOrEmpty(_searchText))
                    {
                        query = query.Where(c => c.Name != null && c.Name.Contains(_searchText));
                    }


                    query = query.OrderBy(c => c.Name).Take(50);

                    AutoCompleateResults = query.AsEnumerable()
                        .Select(c =>
                        {
                            var card = IoC.Get<QuickCardViewModel>();
                            card.Card = c;
                            return card.Card.Name;
                        })
                        .ToArray();

                    NotifyOfPropertyChange(() => AutoCompleateResults);
                }
            });
        }


        public IEnumerable<IResult> Search()
        {
            //yield return Show.Busy();

            yield return new AsyncResult(() =>
            {
                using (IDatabase database = IoC.Get<IDatabase>())
                {
                    var query = database.Cards;

                    //Text filter
                    if (!string.IsNullOrEmpty(_searchText))
                    {
                        query = query.Where(c => c.Name != null && c.Name.Contains(_searchText));
                    }

                    //Color filter
                    if (!this.AnyColor)
                    {
                        query = query.Where(c => (c.Color & this.Color) == c.Color);
                        if (!this.Colorless)
                        {
                            query = query.Where(c => c.Color != Color.Colorless);
                        }
                    }

                    //Card type filter
                    if (!this.AnyType)
                    {
                        var where = PredicateBuilder.False<ICard>();
                        if (this.Artifacts)
                        {
                            where = where.Or(c => c.Type.Contains("Artifact"));
                        }
                        if (this.Creatures)
                        {
                            where = where.Or(c => c.Type.Contains("Creature"));
                        }
                        if (this.Lands)
                        {
                            where = where.Or(c => c.Type.Contains("Land"));
                        }
                        if (this.Enchantments)
                        {
                            where = where.Or(c => c.Type.Contains("Enchantment"));
                        }
                        if (this.Sorceries)
                        {
                            where = where.Or(c => c.Type.Contains("Sorcery"));
                        }
                        if (this.Instants)
                        {
                            where = where.Or(c => c.Type.Contains("Instant"));
                        }
                        if (this.Plainswalkers)
                        {
                            where = where.Or(c => c.Type.Contains("Plainswalker"));
                        }
                        query = query.Where(where);
                    }

                    if (!this.AnyExpansion)
                    {
                        var where = PredicateBuilder.True<ICard>();
                        foreach (var item in this.Expansions.Where(e => !e.IsChecked))
                        {
                            where = where.And(c => c.Expansion != item.ID);
                        }
                        query = query.Where(where);
                    }

                    query = query.OrderBy(c => c.Name);//.Take(50);

                    _cardCollection.Cards.Clear();
                    _cardCollection.Cards.AddRange(query);

                }
            });

            //yield return Show.NotBusy();
        }
    }
}
